Security News
Cloudflare Adds Security.txt Setup Wizard
Cloudflare has launched a setup wizard allowing users to easily create and manage a security.txt file for vulnerability disclosure on their websites.
Advanced JavaScript inheritance model providing genuine private members based on John Resig's Inheritance Class.
Advanced JavaScript inheritance model providing genuine private members based on John Resig's Inheritance Class
https://npmjs.org/package/jclass
JClass is a lightweight and flexible JavaScript inheritance model providing genuine private
members using closures. It's applicable in nodejs and normal web browsers. JClass is
implemented using prototype
's and brings along multiple features like e.g. propper (and even
inheritance consistent)instanceof
calls. To come straight to the point:
var Animal = JClass.extend({
// the constructor method
init: function(name) {
// a public value
this.name = name;
},
// a public method
eat: function() {
return this.name + ' eats';
},
// a private method, indicated by 2 leading underscores
__behave: function() {
return this.name + ' behaves';
}
});
// inherit from 'Animal'
var Cat = Animal.extend({
init: function(name, color) {
// call 'init' of the super-class
this._super(name);
this.color = color;
// a private value, indicated by 2 leading underscores
this.__lives = 9;
},
// overwrite 'eat'
eat: function() {
var msg = this.__behave();
// 'this._super' references Animal's 'eat' method
return msg + ' because ' + this._super() + ' fish';
},
// getter for '__lives'
getLives: function() {
return this.__lives;
}
});
var simon = new Cat('simon', 'white');
console.log(simon instanceof Cat); // true
console.log(simon instanceof JClass); // true
console.log(simon.name); // 'simon'
console.log(simon.__behave()); // TypeError: Object has no method '__behave'
console.log(simon.eat()); // 'simon behaves because simon eats fish'
console.log(simon.__lives); // undefined
console.log(simon.getLives()); // 9
This little example shows only the basics. It's even possible to customize and optimize JClass for
the various needs of your code by using options
(e.g.
you can change the naming scheme of private members). Take a look at the examples
to get a picture of what is possible and how it's working.
For node (using npm):
npm install jclass
For web browsers:
<script src="/path/to/jclass.min.js"></script>
_super
methodsvar Vehicle = JClass.extend({
init: function(type) {
this.type = type;
},
drive: function() {
return 'driving';
}
});
var Car = Vehicle.extend({
init: function(color) {
// call the super 'init'
this._super('car');
this.color = color;
},
drive: function() {
// call the super 'drive'
return this._super() + ' on 4 tires';
}
});
var myCar = new Car('red');
console.log(myCar.drive()); // 'driving on 4 tires'
var Vehicle = JClass.extend({
init: function(type, price) {
this.type = type;
// a private value, indicated by 2 leading underscores
// because 'privatePattern' is /__.*/ by default
this.__price = price
// a private value using the 'private object'
this.__.consumption = 'too much';
},
// a private method
__drive: function() {
return 'driving';
}
});
var Car = Vehicle.extend({
init: function(color, price) {
this._super('car', price);
this.color = color;
},
// a getter for 'this.__price'
getPrice: function() {
return this.__price;
},
forceDrive: function() {
return this.__drive();
}
});
var myCar = new Car('red', 10000);
console.log(myCar.__price); // undefined
console.log(myCar.getPrice()); // 10000
console.log(myCar.__.consumption); // undefined
console.log(myCar.__drive()); // TypeError: Object has no method '__drive'
console.log(myCar.forceDrive()); // 'driving'
tracking
var opts = {
tracking: false
};
var Vehicle = JClass.extend({
init: function(type, price) {
this.type = type;
// won't be private since there is no tracking
this.__price = price
// values of the 'private object' stay private though!
this.__.consumption = 'too much';
},
// still a private method since tracking does not affect methods
// (methods are kown before the first method call)
__drive: function() {
return 'driving';
}
}, opts); // note the second parameter
var Car = Vehicle.extend({
init: function(color, price) {
this._super('car', price);
this.color = color;
},
forceDrive: function() {
return this.__drive();
}
});
var myCar = new Car('red', 10000);
console.log(myCar.__price); // 10000
console.log(myCar.__drive()); // TypeError: Object has no method '__drive'
console.log(myCar.forceDrive()); // 'driving'
extendable
var opts = {
extendable: false
};
var Vehicle = JClass.extend({
init: function(type) {
this.type = type;
// a private value
this.__secret = 'yay!';
}
}, opts); // note the second parameter
var CarHack = Vehicle.extend({
init: function() {
this._super('car');
},
// try to get the '__secret'
getSecret: function() {
return this.__secret;
}
});
// 'CarHack' won't be assigned since 'Vehicle' cannot be subclassed anymore
var opts = {
ctorName : 'ctor', // the constructor name
superName : '_parent', // the super method name
privatePattern: '/^__.+__$/', // the naming scheme
privateName : '_private' // the name of the private object
};
var Vehicle = JClass.extend({
ctor: function(type) {
this.type = type;
// a private value
this.__secret__ = 'yay!';
// a private value using the 'private object'
this._private.foo = 'bar';
},
// a private method
__drive__: function() {
return 'driving';
}
});
var Car = Vehicle.extend({
ctor: function(color) {
// call the super 'init'
this._parent('car');
this.color = color;
},
tellSecrets: function() {
return this.__drive__() + ' ' + this.__secret__;
}
});
var myCar = newCar('red');
console.log(myCar.tellSecrets()); // 'driving yay!'
The signature of extend
is
var SubClass = JClass.extend(properties [, options]);
properties
- (Object, mandatory)
- An object that defines the methods of your class. See John Resig's Simple Inheritance technique for more details.
options
- (Object, optional)
- An object containing
extendable
- (Boolean, default: true)
- When true, another subclass can inherit from this class. When false, this class cannot be
subclassed (e.g. like final
classes in Java).
ctorName
- (String, default: 'init')
- The name of the method that is invoked when a new instance of your class is created via
new MyClass()
. All passed arguments are applied to this method (OO speaking: the constructor's
name).
superName
- (String, default: '_super')
- The name of the methods of the super-class.
When you call (e.g.) this._super()
in your init
method, the init
method of the super-class
is called.
enablePrivacy
- (String, default: true)
- When false, this is equivalent to privatePattern = null
plus privateName = null
(see
below).
privatePattern
- (RegExp, default: /^__.+/)
- A regular expression that defines how your
private members look like. /^__.+/
would find __fooFn
but not _barFn
. Null means that
there will be no private members.
privateName
- (String, default: '__')
- In addition to values/methods that match the privatePattern
, another private object named
privateName
is visible in every method's scope. In some cases, you may use this object instead
of using tracking
(see below). Null means that no additional private object will be used.
tracking
- (Boolean, default: true)
- tracking
means that all members of an instance are compared before and after a method call
in order to track down any addition or deletion of private values (not methods!). When you call
(e.g.) 'this.__foo = 123' inside a method, the key __foo
(that also matches the
privatePattern
) was obviously added and will be detected by the before/after comparison. If
your classes have a lot of members, you should use the additional private object defined by
privateName
to reduce the number of comparisons. Note: when false, all non-methods (even if
they match the 'privatePattern') won't be private (this.__foo
in our example).
methodsKey
- (String, default: '_jcMethods_')
- The name of the object that holds all private methods during a method call. Note: you only
need to change this value in case of a name collision with your code.
depthKey
- (String, default: '_jcDepth_')
- The name of the depth value (0 for JClass, 1 for the first derived class, 2 for the second
...). Note: you only need to change this value in case of a name collision with your code.
callerDepthKey
- (String, default: '_jcCallerDepth_')
- The name of the depth value of the initial caller. Note: you only need to change this value
in case of a name collision with your code.
Please note: when extending an existing class, please use identical values for the options
ctorName
, superName
, privatePattern
and privateName
in order to keep the prototype/inheritence model
consistent!
JClass.noConflict()
Use this method when JClass
interfers with your code. It returns a reference to the JClass
base
object and resets the JClass
variable to its initial value.
Marcel R. (riga)
FAQs
Advanced but lightweight and fast Javascript inheritance model providing class members and prototype conversion.
The npm package jclass receives a total of 23,965 weekly downloads. As such, jclass popularity was classified as popular.
We found that jclass demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Cloudflare has launched a setup wizard allowing users to easily create and manage a security.txt file for vulnerability disclosure on their websites.
Security News
The Socket Research team breaks down a malicious npm package targeting the legitimate DOMPurify library. It uses obfuscated code to hide that it is exfiltrating browser and crypto wallet data.
Security News
ENISA’s 2024 report highlights the EU’s top cybersecurity threats, including rising DDoS attacks, ransomware, supply chain vulnerabilities, and weaponized AI.